<template>
    <div class="mark-line" ref="lineRef">
        <div
            v-for="line in lines"
            :key="line"
            class="line"
            :class="line.includes('x') ? 'xline' : 'yline'"
            v-show="lineStatus[line] || false"
        ></div>
    </div>
</template>

<script>
import { mapState, mapGetters } from "vuex";
export default {
    name: "subgroup",
    inject: ["contain", "container"],
    provide() {
        return {
            contain: this.contain,
            container: this.container
        };
    },
    components: {},
    props: {
        nav: {
            type: Array,
            default: () => {
                return [];
            }
        }
    },
    data() {
        return {
            lines: ["xt", "xc", "xb", "yl", "yc", "yr"], // 分别对应三条横线和三条竖线
            diff: 3, // 相距 3 像素将自动吸附
            lineStatus: {
                xt: false,
                xc: false,
                xb: false,
                yl: false,
                yc: false,
                yr: false
            }
        };
    },
    computed: {
        ...mapState({
            globalEventList: (state) => state.event.globalEventList,
            activeComps: (state) => state.activeComps,
            compsList: (state) => state.compsList
        }),
        ...mapGetters(["activeCompsIndex"]),
        isBuild() {
            return this.$route ? this.$route.name === "build" : false;
        },
        isKeysCtrl() {
            return this.contain.isKeysCtrl;
        }
    },
    mounted() {},
    methods: {
        hideLine() {
            Object.keys(this.lineStatus).forEach((line) => {
                this.lineStatus[line] = false;
            });
        },

        showLine(isDownward, isRightward) {
            let lines = {};
            let aLines =
                this.$refs.lineRef &&
                this.$refs.lineRef.getElementsByClassName("line");
            if (aLines) {
                for (let i = 0; i < this.lines.length; i++) {
                    lines[this.lines[i]] = [aLines[i]];
                }
            }

            const components = this.compsList;
            const curComponentStyle = this.getComponentRotatedStyle({
                rotate: 0,
                top: this.activeComps[0].top,
                left: this.activeComps[0].left,
                width: this.activeComps[0].component.width,
                height: this.activeComps[0].component.height
            });
            const curComponentHalfwidth = curComponentStyle.width / 2;
            const curComponentHalfHeight = curComponentStyle.height / 2;
            this.hideLine();
            components.forEach((component) => {
                // if (component.index == this.activeComps[0].index) return;
                const componentStyle = this.getComponentRotatedStyle({
                    rotate: 0,
                    top: component.top,
                    left: component.left,
                    width: component.component.width,
                    height: component.component.height
                });
                const { top, left, bottom, right } = componentStyle;
                const componentHalfwidth = componentStyle.width / 2;
                const componentHalfHeight = componentStyle.height / 2;
                const conditions = {
                    top: [
                        {
                            isNearly: this.isNearly(curComponentStyle.top, top),
                            lineNode: lines.xt[0], // xt
                            line: "xt",
                            dragShift: top,
                            lineShift: top
                        },
                        {
                            isNearly: this.isNearly(
                                curComponentStyle.bottom,
                                top
                            ),
                            lineNode: lines.xt[0], // xt
                            line: "xt",
                            dragShift: top - curComponentStyle.height,
                            lineShift: top
                        },
                        {
                            // 组件与拖拽节点的中间是否对齐
                            isNearly: this.isNearly(
                                curComponentStyle.top + curComponentHalfHeight,
                                top + componentHalfHeight
                            ),
                            lineNode: lines.xc[0], // xc
                            line: "xc",
                            dragShift:
                                top +
                                componentHalfHeight -
                                curComponentHalfHeight,
                            lineShift: top + componentHalfHeight
                        },
                        {
                            isNearly: this.isNearly(
                                curComponentStyle.top,
                                bottom
                            ),
                            lineNode: lines.xb[0], // xb
                            line: "xb",
                            dragShift: bottom,
                            lineShift: bottom
                        },
                        {
                            isNearly: this.isNearly(
                                curComponentStyle.bottom,
                                bottom
                            ),
                            lineNode: lines.xb[0], // xb
                            line: "xb",
                            dragShift: bottom - curComponentStyle.height,
                            lineShift: bottom
                        }
                    ],
                    left: [
                        {
                            isNearly: this.isNearly(
                                curComponentStyle.left,
                                left
                            ),
                            lineNode: lines.yl[0], // yl
                            line: "yl",
                            dragShift: left,
                            lineShift: left
                        },
                        {
                            isNearly: this.isNearly(
                                curComponentStyle.right,
                                left
                            ),
                            lineNode: lines.yl[0], // yl
                            line: "yl",
                            dragShift: left - curComponentStyle.width,
                            lineShift: left
                        },
                        {
                            // 组件与拖拽节点的中间是否对齐
                            isNearly: this.isNearly(
                                curComponentStyle.left + curComponentHalfwidth,
                                left + componentHalfwidth
                            ),
                            lineNode: lines.yc[0], // yc
                            line: "yc",
                            dragShift:
                                left +
                                componentHalfwidth -
                                curComponentHalfwidth,
                            lineShift: left + componentHalfwidth
                        },
                        {
                            isNearly: this.isNearly(
                                curComponentStyle.left,
                                right
                            ),
                            lineNode: lines.yr[0], // yr
                            line: "yr",
                            dragShift: right,
                            lineShift: right
                        },
                        {
                            isNearly: this.isNearly(
                                curComponentStyle.right,
                                right
                            ),
                            lineNode: lines.yr[0], // yr
                            line: "yr",
                            dragShift: right - curComponentStyle.width,
                            lineShift: right
                        }
                    ]
                };
                const needToShow = [];
                let rotate = 0;
                Object.keys(conditions).forEach((key) => {
                    // 遍历符合的条件并处理
                    conditions[key].forEach((condition) => {
                        if (!condition.isNearly) return;
                        // 修改当前组件位移
                        this.activeComps[0][key] = condition.dragShift;
                        this.$store.commit("setActiveComps", {
                            isKeysCtrl: false,
                            ...this.activeComps[0]
                        });
                        if (condition.lineNode) {
                            condition.lineNode.style[
                                key
                            ] = `${condition.lineShift}px`;
                            needToShow.push(condition.line);
                        }
                    });
                });
                // 同一方向上的线只显示一条，例如多条横条只显示一条横线
                if (needToShow.length) {
                    this.chooseTheTureLine(needToShow, isDownward, isRightward);
                }
            });
        },

        translatecurComponentShift(key, condition, curComponentStyle) {
            const { width, height } = this.activeComps.style;
            if (key == "top") {
                return Math.round(
                    condition.dragShift -
                        (height - curComponentStyle.height) / 2
                );
            }

            return Math.round(
                condition.dragShift - (width - curComponentStyle.width) / 2
            );
        },

        chooseTheTureLine(needToShow, isDownward, isRightward) {
            // 如果鼠标向右移动 则按从右到左的顺序显示竖线 否则按相反顺序显示
            // 如果鼠标向下移动 则按从下到上的顺序显示横线 否则按相反顺序显示
            if (isRightward) {
                if (needToShow.includes("yr")) {
                    this.lineStatus.yr = true;
                } else if (needToShow.includes("yc")) {
                    this.lineStatus.yc = true;
                } else if (needToShow.includes("yl")) {
                    this.lineStatus.yl = true;
                }
            } else {
                // eslint-disable-next-line no-lonely-if
                if (needToShow.includes("yl")) {
                    this.lineStatus.yl = true;
                } else if (needToShow.includes("yc")) {
                    this.lineStatus.yc = true;
                } else if (needToShow.includes("yr")) {
                    this.lineStatus.yr = true;
                }
            }

            if (isDownward) {
                if (needToShow.includes("xb")) {
                    this.lineStatus.xb = true;
                } else if (needToShow.includes("xc")) {
                    this.lineStatus.xc = true;
                } else if (needToShow.includes("xt")) {
                    this.lineStatus.xt = true;
                }
            } else {
                if (needToShow.includes("xt")) {
                    this.lineStatus.xt = true;
                } else if (needToShow.includes("xc")) {
                    this.lineStatus.xc = true;
                } else if (needToShow.includes("xb")) {
                    this.lineStatus.xb = true;
                }
            }
        },

        isNearly(dragValue, targetValue) {
            return Math.abs(dragValue - targetValue) <= this.diff;
        },
        // 获取一个组件旋转 rotate 后的样式
        getComponentRotatedStyle(style) {
            style = { ...style };
            if (style.rotate != 0) {
                const newWidth =
                    style.width * this.cos(style.rotate) +
                    style.height * this.sin(style.rotate);
                const diffX = (style.width - newWidth) / 2; // 旋转后范围变小是正值，变大是负值
                style.left += diffX;
                style.right = style.left + newWidth;

                const newHeight =
                    style.height * this.cos(style.rotate) +
                    style.width * this.sin(style.rotate);
                const diffY = (newHeight - style.height) / 2; // 始终是正
                style.top -= diffY;
                style.bottom = style.top + newHeight;

                style.width = newWidth;
                style.height = newHeight;
            } else {
                style.bottom = style.top + style.height;
                style.right = style.left + style.width;
            }

            return style;
        },
        sin(rotate) {
            return Math.abs(Math.sin(this.angleToRadian(rotate)));
        },
        cos(rotate) {
            return Math.abs(Math.cos(this.angleToRadian(rotate)));
        },
        angleToRadian(angle) {
            return (angle * Math.PI) / 180;
        }
    }
};
</script>

<style lang="scss" scoped>
.mark-line {
    height: 100%;
}
.line {
    background: yellow;
    position: absolute;
    z-index: 1000;
}
.xline {
    width: 100%;
    height: 1px;
}
.yline {
    width: 1px;
    height: 100%;
}
</style>
